package com.mp.approvalreq.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mp.approvalreq.entity.ContentType;
import com.mp.approvalreq.entity.Template;
import com.mp.approvalreq.entity.TemplateComponent;
import com.mp.approvalreq.entity.common.Constants;
import com.plusmoney.exception.RpcServerLogicalException;
import com.plusmoney.util.Utils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 一个generation对应一个模板版本
 */
public class ComponentGenerationUtils {

    /**
     * 如果创建或修改的模板组件不符合规定的组件规范则报错
     *
     * @return
     */
    public static boolean checkGenerationComponent(List<TemplateComponent> components, int userGeneration, Template template) {
        int defaultType = template.getDefaultType();

        // 小于4无需校验,属于老版本
        if (userGeneration < Constants.DEFAULT_GENERATION) {
            return true;
        }

        // generation >= 4时, 如果自定义模板中存在 组件集
        if (defaultType == Template.OTHER) {
            List<Integer> componentGroupNums = new ArrayList<>();
            for (TemplateComponent component : components) {
                if (component.getType() == ContentType.COMPONENT_GROUP) {
                    componentGroupNums.add(component.getNum());
                }
            }

            String componentGroupJson = template.getComponentGroupJson();
            // 两个都为空,表示升级到4版本,但是依然没有使用组件集
            if (ListHelper.isNullEmpty(componentGroupNums) && StringUtils.isEmpty(componentGroupJson)) {
                return true;
            }

            if (ListHelper.isNotNullEmpty(componentGroupNums) && StringUtils.isEmpty(componentGroupJson)) {
                throw new RpcServerLogicalException(1, "关联组件集合不能为空");
            }

            if (ListHelper.isNullEmpty(componentGroupNums) && StringUtils.isNotEmpty(componentGroupJson)) {
                throw new RpcServerLogicalException(1, "关联组件参数错误");
            }

            // [{"num":xx, "id":xx}] 格式校验
            JSONArray array = JSON.parseArray(componentGroupJson);
            for (int i = 0; i < array.size(); i++) {
                JSONObject object = array.getJSONObject(i);
                if (Utils.isNull(object.getInteger(Constants.GROUP_NUM)) || Utils.isNull(object.getInteger(Constants.GROUP_ID))) {
                    throw new RpcServerLogicalException(1, "关联组件格式错误");
                }
            }

            return true;
        }

        return true;
    }

    private static List<TemplateComponent> getTemplateComponentList(Template template) {
        List<TemplateComponent> templateComponents;
        try {
            templateComponents = JSONArray.parseArray(template.getTemplateComponent(), TemplateComponent.class);
        } catch (Exception e) {
            throw new RpcServerLogicalException(1, "数据格式错误");
        }

        if (ListHelper.isNullEmpty(templateComponents)) {
            throw new RpcServerLogicalException(1, "模板内容为空");
        }
        return templateComponents;
    }

    /*
     *   新版本的管理员修改了模板,如果该模板没有使用到新版本的功能,则允许该公司其它老版本也能使用该模板;
     *                       如果该模板使用到了新版本的功能,则需要老版本的用户更新版本后才能使用;
     *   具体做法: 判断管理员新建和修改的模板组件,如果组件中存在新模板定义的样式,则该模板的generation == 用户当前版本的generation
     *           如果组件中不存在新模板的定义的样式,则该模板的generation == 该模板类型上次的generation
     *
     *   目前: 报销模板的generation = 1, 补打卡模板的generation = 2, 因此从此时开始,所有的新建的模板初始化generation = 2
     *
     *   注: 因为安卓有个版本上了3,这里默认之后的修改的版本都从4开始
     */

    /**
     * 生成该模板的generation
     *
     * @return
     */
    public static Integer getTemplateGeneration(Template template) {
        List<TemplateComponent> components = getTemplateComponentList(template);
        Integer generation = 0;

        switch (template.getDefaultType()) {
            case Template.EXPENSES:
                EXPENSES expenses = new EXPENSES(components);
                generation = expenses.getGeneration();
                break;

            case Template.LEAVE:
                LEAVE leave = new LEAVE(components);
                generation = leave.getGeneration();
                break;

            case Template.OUTDOOR:
                OUTDOOR outdoor = new OUTDOOR(components);
                generation = outdoor.getGeneration();
                break;

            case Template.PURCHASE:
                NEED_MONEY needMoney = new NEED_MONEY(components);
                generation = needMoney.getGeneration();
                break;

            case Template.APPEND_SIGN:
                RE_CHECK_IN reCheckIn = new RE_CHECK_IN(components);
                generation = reCheckIn.getGeneration();
                break;

            case Template.OTHER:
                OTHER other = new OTHER(components);
                generation = other.getGeneration();
                break;

            case Template.BUSINESS_TRIP:
                BUSINESS_TRIP businessTrip = new BUSINESS_TRIP(components, template.getOutSignOffset());
                generation = businessTrip.getGeneration();
                break;

            case Template.COMPENSATORY_LEAVE:
                COMPENSATORY_LEAVE compensatoryLeave = new COMPENSATORY_LEAVE(components);
                generation = compensatoryLeave.getGeneration();
                break;

            case Template.WORK_OVERTIME:
                WORK_OVERTIME workOvertime = new WORK_OVERTIME(components);
                generation = workOvertime.getGeneration();
                break;

            case Template.DAYS_OFF:
                DAYS_OFF days_off = new DAYS_OFF(components);
                generation = days_off.getGeneration();
                break;

            default:
                break;
        }

        return generation == null ? 0 : generation;
    }


    static abstract class Common {
        private List<TemplateComponent> components;
        static final String DEFAULT_GENERATION = "默认";
        static final Map<String, Integer> generaionMap = new HashMap<String, Integer>() {
            {
                put("默认", 2);

                // 自定义模板组件集的版本为4
                put("组件集", 4);
                put("加班", 4);
                put("调休", 4);
                put("目的地非必填", 4);
            }
        };

        public List<TemplateComponent> getComponents() {
            return components;
        }

        public void setComponents(List<TemplateComponent> components) {
            this.components = components;
        }

        public abstract Integer getGeneration();
    }


    /**
     * 报销模板
     */
    static class EXPENSES extends Common {
        EXPENSES(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 请假模板
     */
    static class LEAVE extends Common {
        LEAVE(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }


    /**
     * 外出模板
     */
    static class OUTDOOR extends Common {
        OUTDOOR(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 申购模板
     */
    static class NEED_MONEY extends Common {
        NEED_MONEY(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 补打卡模板
     */
    static class RE_CHECK_IN extends Common {
        RE_CHECK_IN(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 自定义模板
     */
    static class OTHER extends Common {
        private static final String COMPONENT_GROUP = "组件集";

        OTHER(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            for (TemplateComponent component : getComponents()) {
                // 有组件集又有其它功能的版本

                // 有组件集的版本
                if (component.getType() == ContentType.COMPONENT_GROUP) {
                    return generaionMap.get(COMPONENT_GROUP);
                }

                // 金额汇总,也是generation=4
                if (component.getType() == ContentType.TOTAL_MONEY) {
                    return generaionMap.get(COMPONENT_GROUP);
                }
            }

            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 出差模板
     */
    static class BUSINESS_TRIP extends Common {

        private String outOffset;

        BUSINESS_TRIP(List<TemplateComponent> components, String outOffset) {
            setComponents(components);
            this.outOffset = outOffset;
        }

        @Override
        public Integer getGeneration() {
            if (StringUtils.isNotEmpty(outOffset)) {
                return generaionMap.get("目的地非必填");
            }
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 补假模板
     */
    static class COMPENSATORY_LEAVE extends Common {
        COMPENSATORY_LEAVE(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DEFAULT_GENERATION);
        }
    }

    /**
     * 加班模板
     */
    static class WORK_OVERTIME extends Common {
        private static final String WORK_OVERTIME = "加班";

        WORK_OVERTIME(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(WORK_OVERTIME);
        }
    }

    static class DAYS_OFF extends Common {
        private static final String DAYS_OFF = "调休";

        DAYS_OFF(List<TemplateComponent> components) {
            setComponents(components);
        }

        @Override
        public Integer getGeneration() {
            return generaionMap.get(DAYS_OFF);
        }
    }

}
